//Erstellt von Moritz Liepe
package main;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;

import org.eclipse.draw2d.Label;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;


public class XMLParser {

	private String filename = "";
	
	public XMLParser(String fn){
		filename = fn;
	}

	public ArrayList<Module> getXMLModules(){
		ArrayList<Module> Modules = new ArrayList<Module>(); 
		try {
			
		      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		      
		      DocumentBuilder loader = factory.newDocumentBuilder();
	
		      Document document = loader.parse(filename);
		      
		      Node node = document.getDocumentElement();
		      
		      boolean setTitle =  false;
		      boolean setTitleImage = false;
		      boolean setTitleText = false;
		      String titleImage = "";
		      String titleText = "";
		      ArrayList<IModuleControl> controls = new ArrayList<IModuleControl>();
		    	  
		      if (node.hasChildNodes()){
		    	  for(Node node1 = node.getFirstChild(); node1 != null ; node1 = node1.getNextSibling()){
		    		  String val = node1.getNodeValue();
		    		  if (val != null) val = val.trim();
	    			  
		    		  if(node1.hasChildNodes() && node1.getNodeName().equalsIgnoreCase("module")){
			    		  for(Node node2 = node1.getFirstChild(); node2 != null ; node2 = node2.getNextSibling()){
			    			  if(node2.getNodeName().equalsIgnoreCase("title"))setTitle=true;
			    			  else if(node2.getNodeName().equalsIgnoreCase("control")){
			    				  boolean connectable = false;
			    				  if (node2.getAttributes().getNamedItem("CONNECTABLE").getNodeValue().equalsIgnoreCase("true"))connectable = true;
			    				  controls.add(createControl(node2.getAttributes().getNamedItem("CLASS").getNodeValue(),
			    						  Integer.parseInt(node2.getAttributes().getNamedItem("X").getNodeValue()), 
			    						  Integer.parseInt(node2.getAttributes().getNamedItem("Y").getNodeValue()), 
			    						  Integer.parseInt(node2.getAttributes().getNamedItem("WIDTH").getNodeValue()), 
			    						  Integer.parseInt(node2.getAttributes().getNamedItem("HEIGHT").getNodeValue()), 
			    						  node2.getAttributes().getNamedItem("TYPE").getNodeValue(), 
			    						  node2.getAttributes().getNamedItem("ADDRESS").getNodeValue(), 
			    						  node2.getAttributes().getNamedItem("TOOLTIP").getNodeValue(), 
			    						  connectable));
			    			  }
			    			  val = node2.getNodeValue();
				    		  if (val != null) val = val.trim();
			    			  
			    			  if(node2.hasChildNodes()){
					    		  for(Node node3 = node2.getFirstChild(); node3 != null ; node3 = node3.getNextSibling()){
					    			  if(node3.getNodeName().equalsIgnoreCase("img"))setTitleImage=true;
					    			  else if(node3.getNodeName().equalsIgnoreCase("text") && setTitle)setTitleText=true;
					    			  val = node3.getNodeValue();
						    		  if (val != null) val = val.trim();
						    		  
					    			  if(node3.hasChildNodes()){
							    		  for(Node node4 = node3.getFirstChild(); node4 != null ; node4 = node4.getNextSibling()){
							    			  val = node4.getNodeValue();
								    		  if (val != null) val = val.trim();
								    		  if(setTitleImage)titleImage=val;
								    		  else if(setTitleText)titleText=val;
								    		  
								    		  
							    			  
							    			  
							    		  }
					    			  }
					    			  setTitleImage=false;
					    			  setTitleText=false;
					    		  }
			    			  }
			    			  setTitle = false;
			    		  }
			    		  Module tempMod = getModule(titleImage, titleText, controls, 
			    				  node1.getAttributes().getNamedItem("ID").getNodeValue(), 
			    				  Integer.parseInt((node1.getAttributes().getNamedItem("WIDTH").getNodeValue())), 
			    				  Integer.parseInt(node1.getAttributes().getNamedItem("HEIGHT").getNodeValue()), 
			    				  -1,
			    				  -1, 
			    				  null);
			    		  controls.clear();
			    		  Modules.add(tempMod);
		    		  }
		    	  }
		    	  
		      }
	
		    } catch (IOException ex) {
		      handleParserException(ex);
		    } catch (SAXException ex) {
		      handleParserException(ex);
		    } catch (ParserConfigurationException ex) {
		      handleParserException(ex);
		    } catch (FactoryConfigurationError ex) {
		      handleParserException(ex);
		    }
			catch (Exception ex) {
		      // Maybe IModuleClass not found:
		      handleParserException(ex);
		    }
		    return Modules;
	}
	
	public Module getModuleByID(String ID){
		Module m = new Module();
		try {
			
		      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		      
		      DocumentBuilder loader = factory.newDocumentBuilder();
	
		      Document document = loader.parse(filename);
		      
		      Node node = document.getDocumentElement();
		      
		      boolean setTitle =  false;
		      boolean setTitleImage = false;
		      boolean setTitleText = false;
		      String titleImage = "";
		      String titleText = "";;
		      ArrayList<IModuleControl> controls = new ArrayList<IModuleControl>();
		      
		      if (node.hasChildNodes()){
		    	  for(Node node1 = node.getFirstChild(); node1 != null ; node1 = node1.getNextSibling()){
		    		  if(node1.hasChildNodes() && node1.getNodeName().equalsIgnoreCase("module") && node1.getAttributes().getNamedItem("ID").getNodeValue().equals(ID)){
					    		  for(Node node2 = node1.getFirstChild(); node2 != null ; node2 = node2.getNextSibling()){
					    			  if(node2.getNodeName().equalsIgnoreCase("title"))setTitle=true;
					    			  else if(node2.getNodeName().equalsIgnoreCase("control")){
					    				  boolean connectable = false;
					    				  if (node2.getAttributes().getNamedItem("CONNECTABLE").getNodeValue().equalsIgnoreCase("true"))connectable = true;
					    				  controls.add(createControl(node2.getAttributes().getNamedItem("CLASS").getNodeValue(),
					    						  Integer.parseInt(node2.getAttributes().getNamedItem("X").getNodeValue()), 
					    						  Integer.parseInt(node2.getAttributes().getNamedItem("Y").getNodeValue()), 
					    						  Integer.parseInt(node2.getAttributes().getNamedItem("WIDTH").getNodeValue()), 
					    						  Integer.parseInt(node2.getAttributes().getNamedItem("HEIGHT").getNodeValue()), 
					    						  node2.getAttributes().getNamedItem("TYPE").getNodeValue(), 
					    						  node2.getAttributes().getNamedItem("ADDRESS").getNodeValue(), 
					    						  node2.getAttributes().getNamedItem("TOOLTIP").getNodeValue(), 
					    						  connectable));
					    			  }
					    			  if(node2.hasChildNodes()){
							    		  for(Node node3 = node2.getFirstChild(); node3 != null ; node3 = node3.getNextSibling()){
							    			  if(node3.getNodeName().equalsIgnoreCase("img"))setTitleImage=true;
							    			  else if(node3.getNodeName().equalsIgnoreCase("text") && setTitle)setTitleText=true;
							    			  if(node3.hasChildNodes()){
									    		  for(Node node4 = node3.getFirstChild(); node4 != null ; node4 = node4.getNextSibling()){
									    			  String val = node4.getNodeValue();
										    		  if (val != null) val = val.trim();
										    		  if(setTitleImage)titleImage=val;
										    		  else if(setTitleText)titleText=val;
										    		  
										    		
									    			  
									    			  
									    		  }
							    			  }
							    			  setTitleImage=false;
							    			  setTitleText=false;
							    		  }
					    			  }
					    			  setTitle = false;
					    		  }
			    			  	  
					    		  m = getModule(titleImage, titleText, controls, 
					    				  node1.getAttributes().getNamedItem("ID").getNodeValue(), 
					    				  Integer.parseInt((node1.getAttributes().getNamedItem("WIDTH").getNodeValue())), 
					    				  Integer.parseInt(node1.getAttributes().getNamedItem("HEIGHT").getNodeValue()), 
					    				  -1,
					    				  -1, 
					    				  ((Element)node1).getAttribute("SIMID"));
					    		  controls.clear();
		    		  }
		    	  }
		      }
		    	  
	
		    } catch (IOException ex) {
		      handleParserException(ex);
		    } catch (SAXException ex) {
		      handleParserException(ex);
		    } catch (ParserConfigurationException ex) {
		      handleParserException(ex);
		    } catch (FactoryConfigurationError ex) {
		      handleParserException(ex);
		    } catch (NumberFormatException nfe){
		    	handleParserException(nfe);
		    }
			catch (Exception ex) {
		      // Maybe IModuleClass not found:
		      handleParserException(ex);
		    }
		    return m;
	}
	
	public ArrayList<Object> parseXMLProgram(){
		ArrayList<Object> Elements = new ArrayList<Object>(); 
		try {
			
		      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		      
		      DocumentBuilder loader = factory.newDocumentBuilder();
	
		      Document document = loader.parse(filename);
		      
		      Node node = document.getDocumentElement();
		      
		      boolean setTitle =  false;
		      boolean setTitleImage = false;
		      boolean setTitleText = false;
		      String titleImage = "";
		      String titleText = "";
		      ArrayList<IModuleControl> controls = new ArrayList<IModuleControl>();
		    	  
		      if (node.hasChildNodes()){
		    	  for(Node node1 = node.getFirstChild(); node1 != null ; node1 = node1.getNextSibling()){
		    		  String val = node1.getNodeValue();
		    		  if (val != null) val = val.trim();
	    			  
		    		  if(node1.hasChildNodes() && node1.getNodeName().equalsIgnoreCase("module")){
			    		  
		    			  for(Node node2 = node1.getFirstChild(); node2 != null ; node2 = node2.getNextSibling()){
			    			  if(node2.getNodeName().equalsIgnoreCase("title"))setTitle=true;
			    			  else if(node2.getNodeName().equalsIgnoreCase("control")){
			    				  boolean connectable = false;
			    				  if (node2.getAttributes().getNamedItem("CONNECTABLE").getNodeValue().equalsIgnoreCase("true"))connectable = true;
			    				  IModuleControl tempControl = createControl(node2.getAttributes().getNamedItem("CLASS").getNodeValue(),
			    						  Integer.parseInt(node2.getAttributes().getNamedItem("X").getNodeValue()), 
			    						  Integer.parseInt(node2.getAttributes().getNamedItem("Y").getNodeValue()), 
			    						  Integer.parseInt(node2.getAttributes().getNamedItem("WIDTH").getNodeValue()), 
			    						  Integer.parseInt(node2.getAttributes().getNamedItem("HEIGHT").getNodeValue()), 
			    						  node2.getAttributes().getNamedItem("TYPE").getNodeValue(), 
			    						  node2.getAttributes().getNamedItem("ADDRESS").getNodeValue(), 
			    						  node2.getAttributes().getNamedItem("TOOLTIP").getNodeValue(), 
			    						  connectable);
			    				  if (node2.getAttributes().getNamedItem("CONTROLTEXT") != null)
			    					  ((TextControl) tempControl).setValue(node2.getAttributes().getNamedItem("CONTROLTEXT").getNodeValue());
			    				  tempControl.setID(node2.getAttributes().getNamedItem("ID").getNodeValue());
			    				  controls.add(tempControl);
			    			  }
			    			  val = node2.getNodeValue();
				    		  if (val != null) val = val.trim();
			    			  
			    			  if(node2.hasChildNodes()){
					    		  for(Node node3 = node2.getFirstChild(); node3 != null ; node3 = node3.getNextSibling()){
					    			  if(node3.getNodeName().equalsIgnoreCase("img"))setTitleImage=true;
					    			  else if(node3.getNodeName().equalsIgnoreCase("text") && setTitle)setTitleText=true;
					    			  val = node3.getNodeValue();
						    		  if (val != null) val = val.trim();
						    		  
					    			  if(node3.hasChildNodes()){
							    		  for(Node node4 = node3.getFirstChild(); node4 != null ; node4 = node4.getNextSibling()){
							    			  val = node4.getNodeValue();
								    		  if (val != null) val = val.trim();
								    		  if(setTitleImage)titleImage=val;
								    		  else if(setTitleText)titleText=val;
							    		  }
					    			  }
					    			  setTitleImage=false;
					    			  setTitleText=false;
					    		  }
			    			  }
			    			  setTitle = false;
			    		  }
			    		  
		    			  
			    		  Module tempMod = getModule(titleImage, titleText, controls, 
			    				  node1.getAttributes().getNamedItem("ID").getNodeValue(), 
			    				  Integer.parseInt((node1.getAttributes().getNamedItem("WIDTH").getNodeValue())), 
			    				  Integer.parseInt(node1.getAttributes().getNamedItem("HEIGHT").getNodeValue()), 
			    				  Integer.parseInt(node1.getAttributes().getNamedItem("X").getNodeValue()),
			    				  Integer.parseInt(node1.getAttributes().getNamedItem("Y").getNodeValue()), 
			    				  ((Element)node1).getAttribute("SIMID"));
			    		  controls.clear();
			    		  Elements.add(tempMod);
		    		  }
		    		  else if (node1.getNodeName().equalsIgnoreCase("connection")){
		    			  Connection tempConnection = new Connection();
		    			  tempConnection.setSourceID(node1.getAttributes().getNamedItem("SOURCE").getNodeValue());
		    			  tempConnection.setSourceModuleID(node1.getAttributes().getNamedItem("SOURCEMODULE").getNodeValue());
		    			  tempConnection.setTargetID(node1.getAttributes().getNamedItem("TARGET").getNodeValue());
		    			  tempConnection.setTargetModuleID(node1.getAttributes().getNamedItem("TARGETMODULE").getNodeValue());
		    			  Elements.add(tempConnection);
		    		  }
		    	  }
		    	  
		      }
	
		    } catch (IOException ex) {
		      handleParserException(ex);
		    } catch (SAXException ex) {
		      handleParserException(ex);
		    } catch (ParserConfigurationException ex) {
		      handleParserException(ex);
		    } catch (FactoryConfigurationError ex) {
		      handleParserException(ex);
		    }
			catch (Exception ex) {
		      // Maybe IModuleClass not found:
		      handleParserException(ex);
		    }
		    return Elements;
	}
	
	private static final void handleParserException(Throwable ex) {
	    ex.printStackTrace();
	    Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();  
		String dialogBoxTitle = "Parsing/Writing XML failed";
		String message = "File is not valid: \n" + ex.toString();
		MessageDialog.openInformation(shell, dialogBoxTitle, message);
	}
	
	public IModuleControl createControl(String className,int x, int y, int width, int height, String type, String address, String tooltip, boolean connectable) throws InstantiationException, IllegalAccessException, ClassNotFoundException
	{
		IModuleControl control = (IModuleControl)Class.forName(className).newInstance();

		
		control.setX(x);
		control.setY(y);
		control.setWidth(width);
		control.setHeight(height);
		control.setType(type);
		control.setAddress(address);
		control.setConnectable(connectable);
		
		control.setToolTip(new Label(tooltip));
		control.paint();
		
		return control;
	}
	
	public Module getModule(String titleImage, String titleText, ArrayList<IModuleControl> controls, String id, int width, int height, int x, int y, String simid){
		  Label lbl;
		  if (XMLParser.class.getResourceAsStream("..//icons//"+titleImage) != null) lbl = new Label(titleText, new Image(null, XMLParser.class.getResourceAsStream("..//icons//"+titleImage)));
		  else {
			  Properties props = System.getProperties(); 
			  String path = "";
			  String[] temp;
			  path = props.getProperty("osgi.bundlestore");
			  temp = path.split("configuration");
			  path = temp[0];
			  path += "ModuleImages\\" + titleImage;
			  try {
				  lbl = new Label(titleText, new Image(null, path));
			  }catch (Exception e){
				  lbl = new Label(titleText);
			  }
		  }
		  Module m = new Module(id, width, height);
		  m.setTitle(lbl);
		  m.setTitleImagePath(titleImage);
		  if(simid != null) m.setSIMID(simid);
		  if(x != -1) m.setInitialX(x);
		  if(y != -1) m.setInitialY(y);
		  for(int i=0; i<controls.size(); i++){
			  m.addControl(controls.get(i));
		  }
		  controls.clear();
		  
		  return m;
		
	}

}